home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 11
/
CU Amiga Magazine's Super CD-ROM 11 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-06].iso
/
cucd
/
programming
/
oberonv4
/
source
/
system
/
netsystem.mod
(
.txt
)
< prev
next >
Wrap
Oberon Text
|
1996-07-28
|
13KB
|
420 lines
Syntax10.Scn.Fnt
Syntax10b.Scn.Fnt
MODULE NetSystem;
(*BD, 13.2.96 *)
IMPORT SYSTEM, Texts, Oberon, Input, B := AmigaNetBase;(* insert here the name of your specific module NetBase *)
CONST
(* res values *)
done* = 0; (*everything went ok*)
error* = 1; (*failure occured*)
timeout* = 2; (*opening a connection is timed out*)
(* return values of procedure State *)
closed* = 0; (*connection is closed (neither sending nor receiving)*)
listening* = 1; (*passive connection is listening for a request*)
in* = 2; (*receiving only*)
out* = 3; (*sending only*)
inout* = 4; (*sending and receiving is possible*)
(* any port value *)
anyport* = 0;
anyaddr = 0;
buffersize = 1024;
TYPE
IPAdr* = B.IPAdr; (* Internet Address, where IPAdr[0] contains the most significant byte *)
Connection* = POINTER TO ConnectionDesc; (* TCP-Connection *)
ConnectionDesc* = RECORD
socket: LONGINT;
state: INTEGER;
res*: INTEGER; (*result of LRU operation on a connection (error indication)*)
recvbuffer: ARRAY buffersize OF SYSTEM.BYTE;
nofelems, begidx, endidx: LONGINT;
END;
Socket*= POINTER TO SocketDesc; (* UDP-Connection *)
SocketDesc* = RECORD
socket: LONGINT;
res*: INTEGER; (*result of LRU operation on a socket (error indication)*)
END;
hostname*, gateway*: ARRAY 65 OF CHAR;
user*, passwd*: ARRAY 17 OF CHAR;
hostIP*, anyIP*, allIP*: IPAdr;
PROCEDURE Minimum(a, b: LONGINT): LONGINT;
BEGIN
IF a <= b THEN RETURN a ELSE RETURN b END
END Minimum;
PROCEDURE Start*;
VAR
R: Texts.Reader;
ch: CHAR;
i, j, k, l: INTEGER;
err: LONGINT;
namePtr, namelen: LONGINT;
BEGIN
(********* Get Username/Password *********)
i := 0; j := 0;
Texts.OpenReader(R, Oberon.Par.text, Oberon.Par.pos);
REPEAT Texts.Read(R, ch) UNTIL ch # " ";
IF (ch = 0DX) OR (ch = "%") OR (ch = "/") THEN Input.Read(ch);
WHILE (ch > " ") & (ch # "%") & (ch # "/") & (ch # "@") DO
IF i # 16 THEN user[i] := ch; INC(i) END; Input.Read(ch)
END;
IF (ch = "%") OR (ch = "/") THEN Input.Read(ch);
WHILE ch >= " " DO
IF j # 16 THEN passwd[j] := ch; INC(j); END; Input.Read(ch)
END
END
ELSE
WHILE (ch > " ") & (ch # "%") & (ch # "/") DO
IF i # 16 THEN user[i] := ch; INC(i) END; Texts.Read(R, ch)
END;
IF (ch = "%") OR (ch = "/") THEN Input.Read(ch);
WHILE ch >= " " DO
IF j # 16 THEN passwd[j] := ch; INC(j) END; Input.Read(ch)
END
END
END;
user[i] := 0X; passwd[j] := 0X;
(********* Start NetSystemBase *********)
B.Start();
(******** Get HostName, convert it to hostIP ***********)
IF B.done THEN
B.GetHostName(hostname);
IF B.done THEN
B.GetHostByName(hostname, hostIP);
END
END
END Start;
PROCEDURE Stop*;
BEGIN
B.Stop()
END Stop;
PROCEDURE GetIP* (name: ARRAY OF CHAR; VAR IP: IPAdr);
VAR done: BOOLEAN;
BEGIN
IF ('0' <= name[0]) & (name[0] <= '9') THEN B.GetHostByIP(name, IP) (* dotted-decimal number *)
ELSIF ('A' <= CAP(name[0])) & (CAP(name[0]) <= 'Z') THEN B.GetHostByName(name, IP) (* human name *)
ELSE IP:= anyIP
END;
IF ~B.done THEN IP:= anyIP END
END GetIP;
PROCEDURE GetName* (IP: IPAdr; VAR name: ARRAY OF CHAR);
BEGIN
B.GetHostByAdr(IP, name);
IF ~B.done THEN name[0]:= 0X END
END GetName;
(************************************** TCP ****************************************)
PROCEDURE ReceiveBuffer(C: Connection; VAR buf: ARRAY OF SYSTEM.BYTE; pos: LONGINT; VAR len: LONGINT);
VAR length, help: LONGINT;
BEGIN
length:= 0;
LOOP
help:= len-length;
B.Recv(C.socket, buf, pos+length, help);
IF B.done THEN
INC(length, help);
IF length >= len THEN EXIT END
ELSE
EXIT
END
END;
IF length >= len THEN C.res:=done ELSE C.res:= error END
END ReceiveBuffer;
PROCEDURE Available* (C: Connection): LONGINT;
VAR available, err, len: LONGINT;
ok: BOOLEAN;
BEGIN
available:= 0;
IF (C.state=inout) OR (C.state=in) THEN
available:= B.Available(C.socket);
IF B.done & (available > 0) THEN
len:= Minimum(Minimum(buffersize - C.nofelems, buffersize - C.endidx), available);
ReceiveBuffer(C, C.recvbuffer, C.endidx, len);
IF C.res = done THEN
INC(C.nofelems, len);
C.endidx:= (C.endidx + len) MOD buffersize;
available:= available - len
END
ELSIF available = -1 THEN
C.res:= error;
available:= 0 (* reset available to have a correct return value *)
ELSE C.res:= done (* available = 0 *)
END
END;
RETURN available + C.nofelems
END Available;
PROCEDURE Receive(C: Connection; VAR buf: ARRAY OF SYSTEM.BYTE; beg, len: LONGINT; VAR res: INTEGER);
VAR err, available: LONGINT;
BEGIN
IF (C.state=inout) OR (C.state=in) THEN
WHILE (C.nofelems > 0) & (len > 0) DO
buf[beg]:= C.recvbuffer[C.begidx];
INC(beg); C.begidx:= (C.begidx + 1) MOD buffersize;
DEC(len); DEC(C.nofelems)
END;
WHILE len > 0 DO
available:= B.Available(C.socket);
IF B.done & (available > 0) THEN
available:= Minimum(available, len);
ReceiveBuffer(C, buf, beg, available);
IF C.res= done THEN
INC(beg, len); DEC(len, available)
END
ELSE C.res:= error; len := 0;
END
END
ELSE C.res:= error (* Reveive on a Connection with state=out OR state=listening *)
END;
res:= C.res
END Receive;
PROCEDURE Send(C: Connection; VAR buf: ARRAY OF SYSTEM.BYTE; beg, len: LONGINT; VAR res: INTEGER);
VAR help: LONGINT;
BEGIN
IF (C.state=inout) OR (C.state=out) THEN
WHILE len > 0 DO
help:= len;
B.Send(C.socket, buf, beg, help);
IF B.done THEN
res:= done;
DEC(len, help);
INC(beg, help)
ELSE
res:= error;
len:= 0
END
END;
ELSE res:= error (* Send on a Connection with state=in OR state=listening *)
END;
C.res:= res
END Send;
PROCEDURE OpenConnection* (VAR C: Connection; locPort: INTEGER; remIP: IPAdr; remPort: INTEGER;
VAR res: INTEGER);
VAR socket, err: LONGINT;
myaddr, partneraddr : B.Sockaddrin;
BEGIN
IF remPort = anyport THEN remIP:= anyIP END;
B.Socket(socket, B.AFINET, B.SOCKSTREAM, B.IPPROTOTCP);
IF B.done THEN
IF remIP = anyIP THEN (* TCP-Server *)
myaddr.sinfamily:= B.AFINET;
myaddr.sinaddr:= anyIP;
myaddr.sinport:= B.IntToNet(locPort);
B.Bind(socket, myaddr);
IF B.done THEN
B.Listen(socket);
IF B.done THEN
B.SetLinger(socket);
NEW(C);
C.socket:= socket;
C.state:= listening;
C.nofelems:= 0; C.begidx:= 0; C.endidx:= 0;
C.res:= done;
res:= done
ELSE B.Close(socket); res:= error
END
ELSE B.Close(socket); res:= error
END
ELSE (* TCP-Client *)
partneraddr.sinfamily:= B.AFINET;
partneraddr.sinaddr:= remIP;
partneraddr.sinport:= B.IntToNet(remPort);
B.Connect(socket, partneraddr);
IF B.done THEN
B.SetLinger(socket);
NEW(C);
C.socket:= socket;
C.state:= inout;
C.nofelems:= 0; C.begidx:= 0; C.endidx:= 0;
C.res:= done;
res:= done
ELSE
B.Close(socket);
res:= error
END
END
END
END OpenConnection;
PROCEDURE CloseConnection* (C: Connection);
VAR err: LONGINT;
BEGIN
IF C # NIL THEN
B.Close(C.socket);
IF B.done THEN
C.res:= done;
C.state:= closed
ELSE C.res:= error
END
END
END CloseConnection;
PROCEDURE Requested* (C: Connection): BOOLEAN;
BEGIN
RETURN (C.state = listening) & B.Requested(C.socket) & (B.done)
END Requested;
PROCEDURE Accept* (C: Connection; VAR newC: Connection; VAR res: INTEGER);
VAR newsocket: LONGINT;
ok: BOOLEAN;
BEGIN
IF C.state= listening THEN
B.Accept(C.socket, newsocket);
IF B.done THEN
NEW(newC);
newC.socket:= newsocket;
newC.state:= inout;
newC.res:= done;
newC.nofelems:= 0; newC.begidx:= 0; newC.endidx:= 0;
res:=done
ELSE res:= error
END
ELSE res:= error
END
END Accept;
PROCEDURE State* (C: Connection): INTEGER;
BEGIN
IF (~B.Connected(C.socket)) & (B.done) THEN C.state:= closed END;
RETURN C.state
END State;
PROCEDURE GetPartner* (C:Connection; VAR remIP: IPAdr; VAR remPort: INTEGER);
VAR addr: B.Sockaddrin;
len, err: LONGINT;
BEGIN
B.GetPeerName(C.socket, addr);
IF B.done THEN remIP:= addr.sinaddr; remPort:= addr.sinport
ELSE remIP:= anyIP; remPort:= anyport
END
END GetPartner;
(*----- Read -----*)
PROCEDURE Read* (C: Connection; VAR ch: CHAR);
BEGIN Receive(C, ch, 0, 1, C.res)
END Read;
PROCEDURE ReadBytes* (C: Connection; pos, len: LONGINT; VAR buf: B.Data);
BEGIN Receive(C, buf, pos, len, C.res);
END ReadBytes;
PROCEDURE ReadBool* (C: Connection; VAR b: BOOLEAN);
BEGIN Receive(C, b, 0, 1, C.res);
END ReadBool;
PROCEDURE ReadInt* (C: Connection; VAR x: INTEGER);
BEGIN Receive(C, x, 0, 2, C.res); x:= B.NetToInt(x)
END ReadInt;
PROCEDURE ReadLInt* (C: Connection; VAR x: LONGINT);
BEGIN Receive(C, x, 0, 4, C.res); x:= B.NetToLInt(x);
END ReadLInt;
PROCEDURE ReadString* (C: Connection; VAR s: ARRAY OF CHAR);
ch, ch0: CHAR;
i: INTEGER;
BEGIN i := -1; ch := 0X;
REPEAT INC(i);
ch0 := ch; Receive(C, ch, 0, 1, C.res); s[i] := ch;
UNTIL (C.res = error) OR (ch = 0X) OR (ch = 0AX);
IF (ch = 0AX) & (ch0 = 0DX) THEN s[i - 1] := 0X
ELSE s[i] := 0X
END
END ReadString;
(*----- Write -----*)
PROCEDURE Write* (C: Connection; ch: CHAR);
BEGIN Send(C, ch, 0, 1, C.res)
END Write;
PROCEDURE WriteBytes* (C: Connection; pos, len: LONGINT; VAR buf: B.Data);
BEGIN Send(C, buf, pos, len, C.res)
END WriteBytes;
PROCEDURE WriteBool* (C: Connection; b: BOOLEAN);
BEGIN Send(C, b, 0, 1, C.res)
END WriteBool;
PROCEDURE WriteInt* (C: Connection; x: INTEGER);
BEGIN x:= B.IntToNet(x); Send(C, x, 0, 2, C.res)
END WriteInt;
PROCEDURE WriteLInt* (C: Connection; x: LONGINT);
BEGIN x:= B.LIntToNet(x); Send(C, x, 0, 4, C.res)
END WriteLInt;
PROCEDURE WriteString* (C: Connection; s: ARRAY OF CHAR);
cs: ARRAY 2 OF CHAR;
i: INTEGER;
BEGIN i := 0;
WHILE s[i] # 0X DO INC(i) END;
Send(C, s, 0, i, C.res);
cs[0] := 0DX; cs[1] := 0AX;
Send(C, cs, 0, 2, C.res)
END WriteString;
(******************************** UDP **************************************)
PROCEDURE OpenSocket* (VAR S: Socket; locPort: INTEGER; VAR res: INTEGER);
VAR socket, err, port: LONGINT;
myaddr: B.Sockaddrin;
BEGIN
B.Socket(socket, B.AFINET, B.SOCKDGRAM, B.IPPROTOUDP);
IF B.done THEN
IF locPort # anyport THEN
myaddr.sinfamily:= B.AFINET;
myaddr.sinaddr:= anyIP;
myaddr.sinport:= B.IntToNet(locPort);
B.Bind(socket, myaddr);
IF B.done THEN
NEW(S);
S.socket:= socket;
S.res:= done;
res:= done;
ELSE
B.Close(socket);
res:= error
END
END
END
END OpenSocket;
PROCEDURE CloseSocket* (S: Socket);
VAR err: LONGINT;
BEGIN
B.Close(S.socket);
END CloseSocket;
PROCEDURE AvailableDG* (S: Socket): LONGINT;
VAR err, result: LONGINT;
BEGIN
RETURN B.Available(S.socket)
END AvailableDG;
PROCEDURE SendDG* (S: Socket; remIP: IPAdr; remport: INTEGER; pos, len: LONGINT; VAR buf: B.Data);
VAR remaddr: B.Sockaddrin;
addr, res: LONGINT;
ok: BOOLEAN;
BEGIN
remaddr.sinfamily:= B.AFINET;
remaddr.sinport:= B.IntToNet(remport);
remaddr.sinaddr:= remIP;
B.SendTo(S.socket, remaddr, buf, pos, len);
IF B.done THEN S.res := done
ELSE S.res:= error
END
END SendDG;
PROCEDURE ReceiveDG* (S: Socket; VAR remIP: IPAdr; VAR remport: INTEGER; pos: LONGINT; VAR len: LONGINT; VAR buf: B.Data);
VAR remaddr: B.Sockaddrin;
BEGIN
B.RecvFrom(S.socket, remaddr, buf, pos, len);
IF B.done THEN
remIP:= remaddr.sinaddr;
remport:= B.NetToInt(remaddr.sinport);
S.res:= done;
ELSE
S.res:=error
END
END ReceiveDG;
PROCEDURE PutInt* (VAR buf: B.Data; pos, x: INTEGER);
BEGIN
ASSERT(pos <= LEN(buf) - SIZE(INTEGER));
x:= B.IntToNet(x);
SYSTEM.MOVE(SYSTEM.ADR(x), SYSTEM.ADR(buf[pos]), SIZE(INTEGER))
END PutInt;
PROCEDURE PutLInt* (VAR buf: B.Data; pos: INTEGER; x: LONGINT);
BEGIN
ASSERT(pos <= LEN(buf) - SIZE(LONGINT));
x:= B.LIntToNet(x);
SYSTEM.MOVE(SYSTEM.ADR(x), SYSTEM.ADR(buf[pos]), SIZE(LONGINT))
END PutLInt;
PROCEDURE GetInt* (VAR buf: ARRAY OF SYSTEM.BYTE; pos: INTEGER; VAR x: INTEGER);
BEGIN
ASSERT(pos <= LEN(buf) - SIZE(INTEGER));
SYSTEM.MOVE(SYSTEM.ADR(buf[pos]), SYSTEM.ADR(x), SIZE(INTEGER));
x:= B.NetToInt(x)
END GetInt;
PROCEDURE GetLInt* (VAR buf: ARRAY OF SYSTEM.BYTE; pos: INTEGER; VAR x: LONGINT);
BEGIN
ASSERT(pos <= LEN(buf) - SIZE(LONGINT));
SYSTEM.MOVE(SYSTEM.ADR(buf[pos]), SYSTEM.ADR(x), SIZE(LONGINT));
x:= B.NetToLInt(x)
END GetLInt;
BEGIN
anyIP[0] := CHR(0); anyIP[1] := CHR(0); anyIP[2] := CHR(0); anyIP[3] := CHR(0)
END NetSystem.